package com.banggood.upms.web;

import com.banggood.silk.web.api.exception.SkbException;
import com.banggood.upms.bean.exception.ExceptionEnum;
import com.banggood.upms.bean.po.Tree;
import com.banggood.upms.bean.vo.TreeVo;
import com.banggood.upms.bean.vo.search.TreeSearchCriteria;
import com.banggood.upms.bean.vo.validation.AddGroup;
import com.banggood.upms.bean.vo.validation.SearchGroup;
import com.banggood.upms.bean.vo.validation.UpdateGroup;
import com.banggood.upms.common.constant.UpmsConstant;
import com.banggood.upms.service.TreeInfoService;
import com.banggood.upms.service.TreeService;
import com.banggood.upms.converter.TreeConverter;
import io.swagger.annotations.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author XuChuangFeng
 */
@RequestMapping("/tree")
@RestController
@Api(value = "树管理")
public class TreeController {

    protected final Log logger = LogFactory.getLog(getClass());
    @Autowired
    private TreeService treeService;
    @Autowired
    private TreeInfoService treeInfoService;
    @Autowired
    private TreeConverter treeConverter;

    @RequestMapping(value = "/search", method = RequestMethod.POST)
    @ApiOperation(value = "树检索", notes = "返回树及其子节点的树结构信息。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "treeType", value = "树类型,不传入则返回所有树", required = false, paramType = "query", dataType = "String"),
    })
    @ApiResponses({
            @ApiResponse(code = 2007, message = "树类别不存在!"),
    })
    public List<TreeVo> search(@Validated({SearchGroup.class}) TreeSearchCriteria criteria) throws Exception {
        if(!StringUtils.isEmpty(criteria) && !StringUtils.isEmpty(criteria.getTreeType()) && !treeInfoService.ifTreeTypeExists(criteria.getTreeType())) {
            throw new SkbException(ExceptionEnum.TREE_TYPE_NOT_EXISTS.getCode(), ExceptionEnum.TREE_TYPE_NOT_EXISTS.getMessage());
        }
        List<Tree> trees = treeService.selectByCriteria(criteria);
        List<TreeVo> topNodes = treeConverter.outputConverter(trees);
        return topNodes;
    }

    @RequestMapping(value = "/view", method = RequestMethod.GET)
    @ApiOperation(value = "根据树ID获取详情", notes = "GET请求")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, paramType = "query", dataType = "String"),
    })
    public TreeVo selectByPrimaryKey(@RequestParam String id) throws Exception {
        Tree tree = treeService.selectByPrimaryKey(id);
        return tree != null ? treeConverter.singleOutputConverter(tree) : null;
    }

    /**
     * #1，检测这个树类别是否已经有节点存在，如果不存在，那么把当前要插入的节点当做根节点插入
     * #2，判断要插入节点的父节点ID是否不为空，并且数据库中的父节点的类别跟要插入节点的类别一致
     * @param vo
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/add-sub-node", method = RequestMethod.POST)
    @ApiOperation(value = "插入子节点", notes = "必须传入parentId")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "parentId", value = "父节点id", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "nodeCode", value = "节点编码", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "nodeName", value = "节点名称", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "treeType", value = "树类型", required = true, paramType = "query", dataType = "String"),
    })
    @ApiResponses({
            @ApiResponse(code = 2001, message = "父级节点不存在!"),
            @ApiResponse(code = 2010, message = "node code已经存在!"),
            @ApiResponse(code = 5000, message = "操作失败!")
    })
    public TreeVo insertSubNode(@Validated({AddGroup.class}) TreeVo vo) throws Exception {
        Tree tree = treeConverter.singleInputConverter(vo);
        int count = treeService.insert(tree);
        if(count != 1) {
            throw new SkbException(ExceptionEnum.OPERATION_FAILED.getCode(), ExceptionEnum.OPERATION_FAILED.getMessage());
        }
        return treeConverter.singleOutputConverter(treeService.selectByPrimaryKey(tree.getTreeId()));
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ApiOperation(value = "更新接口", notes = "根据系统ID跟系统code（有传入的话）更新系统，code不会被更新，而是作为更新条件。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "treeGroup", value = "树组", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "nodeName", value = "节点名称", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "nodeCode", value = "节点code,传入nodeCode并不会作为更新值，而是作为条件值。", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "remark", value = "备注", required = false, paramType = "query", dataType = "String"),
    })
    @ApiResponses({
            @ApiResponse(code = 5000, message = "操作失败!")
    })
    public String updateByPrimaryKey(@Validated({UpdateGroup.class}) TreeVo vo) throws Exception {
        int count = treeService.updateByPrimaryKey(treeConverter.singleInputConverter(vo));
        if(count != 1) {
            throw new SkbException(ExceptionEnum.OPERATION_FAILED.getCode(), ExceptionEnum.OPERATION_FAILED.getMessage());
        }
        return UpmsConstant.SUCCESS;
    }
}